﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using Krile.Kernel.Control.Surface;
using Krile.Kernel.Bridges;


namespace Krile.Forms.MainForm.Controls.XTab
{
    public class KrileXTabMouseManager : XTabMouseManager
    {
        KrileXTab parent;
        public KrileXTabMouseManager(KrileXTab parent)
            : base(parent)
        {
            this.parent = parent;
        }

        private bool mouseDown = false;
        protected override void OnMouseDown(object sender, MouseEventArgs e)
        {
            mouseDown = true;
            base.OnMouseDown(sender, e);
        }

        protected override void OnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
        {
            mouseDown = false;
            if (Core.Config.Behavior.DetouchableTabWithMouse &&
                !parent.IsWindowTab &&
                prevPoint != null &&
                prevPoint is XTabItem &&
                !((XTabItem)prevPoint).Closed &&
                (e.Location.X < 0 || e.Location.Y < 0 ||
                e.Location.X > parent.Size.Width || e.Location.Y > parent.Size.Height))
            {
                var pf = parent.GetParentForm();
                if (pf != null)
                {
                    var f = GetTransfarable(pf, e.Location);
                    var prevState = pf.WindowState;
                    pf.WindowState = FormWindowState.Normal;
                    if (f == null)
                        f = Core.FormManager.MainForm.CreateSubForm();
                    pf.WindowState = prevState;
                    try
                    {
                        pf.RemoveTab((XTabItem)prevPoint);
                    }
                    finally
                    {
                        f.RegistTab((XTabItem)prevPoint);
                    }
                    f.Activate();
                }
            }
            else
            {
                base.OnMouseUp(sender, e);
            }
            Parent.Cursor = Cursors.Default;
            prevPoint = null;
        }

        protected override void OnMouseMove(object sender, MouseEventArgs e)
        {
            var pp = prevPoint as XTabTLItem;
            if (e.Button == MouseButtons.Left && mouseDown && !parent.IsWindowTab && pp != null && 
                Core.FormManager.MainForm.WindowsTabControl.Visible)
            {
                Rectangle wndRegion = new Rectangle(
                    Core.FormManager.MainForm.PointToScreen(Core.FormManager.MainForm.WindowsTabControl.Location),
                    Core.FormManager.MainForm.WindowsTabControl.ClientRectangle.Size);
                if (wndRegion.HitTest(parent.PointToScreen(e.Location)))
                {
                    parent.DoDragDrop(
                        new XTabDroppable()
                        {
                            OnDroppableThis = new Func<XTab, bool>((f) =>
                            {
                                if (!Core.Config.Behavior.DetouchableTabWithMouse)
                                    return false;
                                var kxt = f as KrileXTab;
                                System.Diagnostics.Debug.WriteLine(kxt + "/" + kxt.IsWindowTab);
                                if (kxt != null && kxt.IsWindowTab)
                                    return true;
                                else
                                    return false;
                            }),
                            OnDropToAppend = new Action<XTab, XTabItem>((p, item) =>
                            {
                                if (!Core.Config.Behavior.DetouchableTabWithMouse)
                                    return;
                                var winitem = item as XTabWindowItem;
                                if (winitem == null) return;
                                try
                                {
                                    parent.GetParentForm().RemoveTab(pp);
                                }
                                finally
                                {
                                    ((IFormEx)winitem.LinkedForm).RegistTab(pp);
                                }
                            }),
                            OnDropToNew = new Action<XTab>((p) =>
                            {
                                if (!Core.Config.Behavior.DetouchableTabWithMouse)
                                    return;
                                try
                                {
                                    parent.GetParentForm().RemoveTab(pp);
                                }
                                finally
                                {
                                    Core.FormManager.MainForm.CreateSubForm().RegistTab(pp);
                                }
                            })
                        },
                         DragDropEffects.All);
                }
            }

            XTabItemBase tib = GetItemByPoint(e.Location);
            if ((e.Button & MouseButtons.Left) == MouseButtons.Left && mouseDown &&
                tib != null && tib is XTabItem &&
                (e.Location.X < 0 || e.Location.Y < 0 ||
                e.Location.X > parent.Size.Width || e.Location.Y > parent.Size.Height))
            {
                var pf = parent.GetParentForm();
                if (pf == null || !(pf is IFormEx))
                {
                    parent.Cursor = Cursors.No;
                    return;
                }
                var f = GetTransfarable(pf, e.Location);
                if (f != null)
                    parent.Cursor = Cursors.UpArrow;
                else
                    parent.Cursor = Cursors.SizeAll;
                return;
            }
            else
            {
                parent.Cursor = Cursors.Default;
                base.OnMouseMove(sender, e);
            }
        }

        protected IFormEx GetTransfarable(IFormEx without, Point location)
        {
            foreach (var f in GetTransfarablesWithZOrder())
            {
                if ((without != null && f == without) || !f.Visible || f.WindowState == FormWindowState.Minimized)
                    continue;
                Rectangle tabRegion = new Rectangle(
                    f.TabControl.PointToScreen(f.TabControl.ClientRectangle.Location),
                    f.TabControl.ClientRectangle.Size);
                if (tabRegion.HitTest(parent.PointToScreen(location)))
                    return f;
                Rectangle winRegion = new Rectangle(
                    Core.FormManager.MainForm.PointToScreen(f.Location),
                    f.Size);
                System.Diagnostics.Debug.WriteLine(winRegion);
                if (winRegion.HitTest(parent.PointToScreen(location)))
                    return null;
            }
            return null;
        }

        private IEnumerable<IFormEx> GetTransfarablesWithZOrder()
        {
            List<IFormEx> forms = new List<IFormEx>(Core.FormManager.GetSubForms());
            forms.Sort(new Comparison<IFormEx>(CompareZOrder));
            return forms;
        }

        protected override void OnDragDrop(object sender, DragEventArgs e)
        {
            base.OnDragDrop(sender, e);
            Core.SaveConfig(false);
        }

        private int CompareZOrder(IFormEx x, IFormEx y)
        {
            return Krile.Imported.Snippets.WindowSystem.CompareZOrder(x.hWndHandle, y.hWndHandle);
        }
    }
}
